package com.gxd.common.utils;


import java.net.InetAddress;

/**
 * GUID（Globally Unique Identifier）生成器
 *
 */
public class GUID {

    static int counter = 0;// 计数器，用于确保生成的GUID在相同毫秒内唯一

    byte[] guts;// 存储GUID的字节数组

    /**
     * 生成下一个GUID，采用同步方法确保线程安全
     *
     * @return 生成的GUID字节数组  ip前字节四个字节 + 时间戳字节前8位 + 计数器字节前4位
     */
    public static synchronized byte[] nextGUID() {
        try {
            // 获取本地主机的IP地址
            byte[] ip = InetAddress.getLocalHost().getAddress();
            // 增加计数器
            ++counter;
            // 创建GUID的字节数组
            byte[] guid = new byte[16];

            // 复制主机IP地址的前4个字节
            for(int i = 0; i < 4; ++i) {
                guid[i] = ip[i];
            }

            // 将当前时间戳转换为字节数组，占据GUID的4到11字节
            byte[] timeAry = long2bytes(System.currentTimeMillis());
            for(int i = 4; i < 12; ++i) {
                guid[i] = timeAry[i - 4];
            }

            // 将计数器转换为字节数组，占据GUID的12到15字节
            //这是因为在相同毫秒内，主机IP地址和时间戳可能相同，通过计数器的递增可以确保生成的GUID不重复
            byte[] counterAry = int2bytes(counter);
            for(int i = 12; i < 16; ++i) {
                guid[i] = counterAry[i - 12];
            }

            return guid;
        } catch (Exception var5) {
            var5.printStackTrace();
            return null;
        }
    }

    /**
     * 默认构造函数，生成一个新的GUID
     */
    public GUID() {
        this.guts = nextGUID();
    }

    /**
     * 构造函数，通过给定的字节数组创建GUID
     *
     * @param guts 存储GUID的字节数组
     * @throws IllegalArgumentException 如果字节数组为null或长度不为16，则抛出此异常
     */
    public GUID(byte[] guts) throws IllegalArgumentException {
        if (guts != null && guts.length == 16) {
            this.guts = guts;
        } else {
            throw new IllegalArgumentException("格式错误，必须传入16字节长的树组");
        }
    }

    /**
     * 判断两个GUID是否相等
     *
     * @param obj 要比较的对象
     * @return 如果是同一GUID返回true，否则返回false
     */
    public boolean equals(Object obj) {
        if (!(obj instanceof GUID)) {
            return false;
        } else {
            if (this != obj) {
                for(int i = 0; i < 16; ++i) {
                    if (((GUID)obj).guts[i] != this.guts[i]) {
                        return false;
                    }
                }
            }

            return true;
        }
    }

    /**
     * 将GUID转换为字符串表示形式
     *
     * @return 字符串表示的GUID
     */
    public String toString() {
        StringBuffer sb = this.toStringBuffer();
        return sb.toString().toUpperCase();
    }

    /**
     * 将GUID转换为StringBuffer
     *
     * @return StringBuffer对象
     */
    private StringBuffer toStringBuffer() {
        StringBuffer str = new StringBuffer();
        byte[] ip = new byte[4];

        // 将主机IP地址的前4个字节复制到ip数组
        for(int i = 0; i < 4; ++i) {
            ip[i] = this.guts[i];
        }

        // 将ip数组转换为十六进制字符串并追加到str
        String s = Integer.toHexString(bytes2int(ip));
        int ii = 8 - s.length();
        for(int i = 0; i < ii; ++i) {
            s = "0" + s;
        }
        str.append(s);

        byte[] time = new byte[8];

        // 将GUID的4到11字节复制到time数组
        for(int i = 4; i < 12; ++i) {
            time[i - 4] = this.guts[i];
        }

        // 将time数组转换为十六进制字符串并追加到str
        s = Long.toHexString(bytes2long(time));
        ii = 16 - s.length();
        for(int i = 0; i < ii; ++i) {
            s = "0" + s;
        }
        str.append(s);

        byte[] count = new byte[4];

        // 将GUID的12到15字节复制到count数组
        for(int i = 12; i < 16; ++i) {
            count[i - 12] = this.guts[i];
        }

        // 将count数组转换为十六进制字符串并追加到str
        s = Integer.toHexString(bytes2int(count));
        ii = 8 - s.length();
        for(int i = 0; i < ii; ++i) {
            s = "0" + s;
        }
        str.append(s);

        return str;
    }

    /**
     * 获取GUID的字节数组
     *
     * @return GUID的字节数组
     */
    public byte[] getData() {
        return this.guts;
    }

    /**
     * 将long类型的数据转换为字节数组
     *
     * @param lParam 要转换的long类型数据
     * @return 转换后的字节数组
     */
    private static synchronized byte[] long2bytes(long lParam) {
        byte[] byteAry = new byte[8];

        for(int i = 0; i < 8; ++i) {
            byteAry[i] = (byte)((int)(lParam >> (7 - i) * 8));
        }

        return byteAry;
    }

    /**
     * 将int类型的数据转换为字节数组
     *
     * @param iParam 要转换的int类型数据
     * @return 转换后的字节数组
     */
    private static synchronized byte[] int2bytes(int iParam) {
        byte[] byteAry = new byte[4];

        for(int i = 0; i < 4; ++i) {
            byteAry[i] = (byte)(iParam >> (3 - i) * 8);
        }

        return byteAry;
    }

    private static synchronized long bytes2long(byte[] byteAry) {
        if (byteAry != null && byteAry.length == 8) {
            long l = 0L;

            for(int i = 0; i < byteAry.length; ++i) {
                l += (long)(byteAry[i] << (7 - i) * 8);
            }

            return l;
        } else {
            return 0L;
        }
    }

    private static synchronized int bytes2int(byte[] byteAry) {
        if (byteAry != null && byteAry.length == 4) {
            int ii = 0;

            for(int i = 0; i < byteAry.length; ++i) {
                ii += byteAry[i] << (3 - i) * 8;
            }

            return ii;
        } else {
            return 0;
        }
    }

    public String getArchiveFormTableName() {
        String tableName = "ARC_FILE_" + (new String(this.toStringBuffer())).toUpperCase().substring(11);
        return tableName;
    }

    public static void main(String[] args) {
        GUID gid1 = new GUID();
        GUID gid2 = new GUID();
        System.out.println(gid1);
        System.out.println(gid2.toString());

    }
}
